package com.have.blog.admin.service.impl;

import com.github.pagehelper.PageHelper;
import com.have.blog.admin.domain.bo.AdminUserDetail;
import com.have.blog.admin.utils.SecurityUtil;
import com.have.blog.security.bo.OnlineAdmin;
import com.have.blog.admin.constant.AdminBlogConstant;
import com.have.blog.admin.constant.AdminMessageConstant;
import com.have.blog.admin.domain.dto.AdminDto;
import com.have.blog.admin.domain.dto.AdminRoleDto;
import com.have.blog.admin.redis.AdminLoginCacheService;
import com.have.blog.admin.service.AdminService;
import com.have.blog.admin.service.AdminRoleService;
import com.have.blog.admin.service.SystemParamService;
import com.have.blog.base.enums.BlogStatus;
import com.have.blog.base.wrapper.ResultCode;
import com.have.blog.base.wrapper.Wrapper;
import com.have.blog.config.hloder.RequestHolder;
import com.have.blog.model.mapper.AdminMapper;
import com.have.blog.model.models.Admin;
import com.have.blog.model.models.AdminExample;
import com.have.blog.picture.service.PictureFeignApi;
import com.have.blog.utils.MyBeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.*;

@Service
@SuppressWarnings("all")
public class AdminServiceImpl implements AdminService {

    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private PictureFeignApi pictureFeignApi;
    @Autowired
    private AdminLoginCacheService adminCacheService;
    @Autowired
    private AdminRoleService roleService;
    @Autowired
    private SystemParamService systemParamService;


    @Override
    public List<AdminDto> getList(AdminDto adminDto) {
        PageHelper.startPage(adminDto.getPageNum(), adminDto.getPageSize());
        // 1. 获取管理员实体
        AdminExample example = new AdminExample();
        AdminExample.Criteria criteria1 = example.createCriteria();
        criteria1.andStatusEqualTo(BlogStatus.ENABLE.getStatus());
        if (!StringUtils.isEmpty(adminDto.getKeyword())) {
            criteria1.andUsernameLike("%" + adminDto.getKeyword() + "%");
            AdminExample.Criteria criteria2 = example.createCriteria();
            criteria2.andNicknameLike("%" + adminDto.getKeyword() + "%");
            example.or(criteria2);
        }
        example.setOrderByClause("create_time desc");
        List<Admin> adminList = adminMapper.selectByExample(example);
        List<AdminDto> resultList = MyBeanUtils.copyListProperties(adminList, AdminDto::new);
        // 2. 获取头像
        List<Integer> headUids = new ArrayList<>();
        resultList.forEach(item -> {
            if (item.getHeadUid() != null) {
                headUids.add(item.getHeadUid());
            }
        });

        if (!CollectionUtils.isEmpty(headUids)) {
            Wrapper<Map<Integer, String>> picturesUrlWrapper = pictureFeignApi.getPicturesUrl(headUids);
            if (picturesUrlWrapper !=null && picturesUrlWrapper.isSuccess()) {
                Map<Integer, String> pictureUrlMap = picturesUrlWrapper.getData();
                resultList.forEach(item -> {
                    item.setPhotoUrl(pictureUrlMap.get(item.getHeadUid()));
                });
            }
        }

        // TODO 用户网盘空间
        for (AdminDto item : resultList) {
            AdminRoleDto roleDto = roleService.getAdminRoleByUid(item.getRoleUid());
            item.setRole(roleDto);
        }
        return resultList;
    }

    @Override
    public Wrapper add(AdminDto adminDto) {
        String mobile = adminDto.getMobile();
        String username = adminDto.getUsername();
        String email = adminDto.getEmail();
        if (StringUtils.isEmpty(username)) {
            return Wrapper.failed(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMessage());
        }
        if (StringUtils.isEmpty(email) && StringUtils.isEmpty(mobile)) {
            return Wrapper.failed(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMessage());
        }
        AdminExample example = new AdminExample();
        example.createCriteria()
                .andUsernameEqualTo(username);
        List<Admin> admins = adminMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(admins)) {
            return Wrapper.failed(AdminMessageConstant.ENTITY_EXIST);
        }
        String defaultPassword = systemParamService.getSystemParamValueByKey(AdminBlogConstant.SYS_DEFAULT_PASSWORD);
        Admin admin = new Admin();
        MyBeanUtils.copyProperties(adminDto, admin);
        admin.setHeadUid(adminDto.getHeadUid());
        admin.setPassword(passwordEncoder.encode(defaultPassword));
        int count = adminMapper.insertSelective(admin);
        /**
         * TODO 这里需要通过SMS模块，发送邮件告诉初始密码 更新成功后，同时申请网盘存储空间 初始化网盘的容量, 单位 B
         */
        if (count > 0) {
            return Wrapper.success(AdminMessageConstant.INSERT_SUCCESS);
        }
        return Wrapper.failed(AdminMessageConstant.INSERT_FAIL);
    }

    @Override
    public Wrapper edit(AdminDto adminDto) {
        Admin admin = adminMapper.selectByPrimaryKey(adminDto.getUid());
        if (admin == null) {
            return Wrapper.illegal();
        }
        AdminExample example = new AdminExample();
        example.createCriteria()
                .andUsernameEqualTo(adminDto.getUsername());
        long count = adminMapper.countByExample(example);
        if (count > 0) {
            return Wrapper.failed("用户重名");
        }

        // TODO UserDetail代替OnlineAdmin
        AdminUserDetail userDetail = SecurityUtil.getUserDetail();
        String adminToken = RequestHolder.getToken();
        if (!StringUtils.isEmpty(adminDto.getUid()) && !adminDto.equals(admin.getUid())) {
            adminCacheService.deleteResourceList(admin.getUid());
            OnlineAdmin onlineAdmin = adminCacheService.getOnlineAdmin(adminToken);
            if (onlineAdmin != null) {
                adminCacheService.deleteOnlineAdmin(adminToken);
                adminCacheService.deleteToken(onlineAdmin.getTokenUId());
            }
        }

        Admin update = new Admin();
        MyBeanUtils.copyProperties(admin, update);
        update.setHeadUid(adminDto.getHeadUid());
        adminMapper.updateByPrimaryKeySelective(update);

        return Wrapper.success();
    }


    @Override
    public Wrapper resetPwd(AdminDto adminDto) {
        String defaultPassword = systemParamService.getSystemParamValueByKey(AdminBlogConstant.SYS_DEFAULT_PASSWORD);
        // 获取当前管理员UID
        ServletRequestAttributes attribute = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Integer adminUid = RequestHolder.getAdminUid();
        Admin admin = adminMapper.selectByPrimaryKey(adminUid);
        if (admin == null) {
            return Wrapper.forbidden();
        }
        // 判断当前管理员是否是admin
        if (AdminBlogConstant.ADMIN.equals(admin.getUsername())
                && !admin.getUid().equals(adminUid)) {
            return Wrapper.forbidden();
        }
        Admin update = adminMapper.selectByPrimaryKey(adminDto.getUid());
        update.setPassword(passwordEncoder.encode(defaultPassword));
        int count = adminMapper.updateByPrimaryKeySelective(update);
        if (count > 0) {
            return Wrapper.success();
        }
        return Wrapper.failed();
    }

    @Override
    public Wrapper deleteBatchAdmin(List<Integer> adminUids) {
        if (CollectionUtils.isEmpty(adminUids)) {
            return Wrapper.illegal();
        }
        Admin admin = new Admin();
        admin.setStatus(BlogStatus.DISABLE.getStatus());
        admin.setUpdateTime(new Date());
        AdminExample example = new AdminExample();
        example.createCriteria()
                .andUidIn(adminUids);
        adminMapper.updateByExampleSelective(admin, example);
        return Wrapper.successWithMessage(AdminMessageConstant.DELETE_SUCCESS);
    }

    @Override
    public AdminDto getMe() {
        Integer adminUid = SecurityUtil.getUserId();
        Admin admin = adminMapper.selectByPrimaryKey(adminUid);
        admin.setPassword(null);
        AdminDto adminDto = new AdminDto();
        MyBeanUtils.copyProperties(admin, adminDto);
        if (!StringUtils.isEmpty(adminDto.getHeadUid())) {
            Wrapper<String> pictureWrapper = pictureFeignApi.getPictureUrl(adminDto.getHeadUid());
            if (pictureWrapper.isSuccess()) {
                adminDto.setPhotoUrl(pictureWrapper.getData());
            }
        }
        return adminDto;
    }

    @Override
    public Wrapper editMe(AdminDto adminDto) {
        Admin admin = new Admin();
        MyBeanUtils.copyProperties(adminDto, admin);
        System.out.println(admin);
        admin.setUpdateTime(new Date());
        int result = adminMapper.updateByPrimaryKeySelective(admin);
        if (result > 0) {
            return Wrapper.successWithMessage(AdminMessageConstant.UPDATE_SUCCESS);
        }
        return Wrapper.failed(AdminMessageConstant.UPDATE_FAIL);
    }

    @Override
    public Wrapper changePwd(String oldPwd, String newPwd) {
        String token = RequestHolder.getToken();
        Integer adminUid = RequestHolder.getAdminUid();
        if (StringUtils.isEmpty(oldPwd) || StringUtils.isEmpty(newPwd)) {
            return Wrapper.illegal();
        }
        Admin admin = adminMapper.selectByPrimaryKey(adminUid);
        boolean matches = passwordEncoder.matches(oldPwd, admin.getPassword());
        if (matches) {
            admin.setPassword(passwordEncoder.encode(newPwd));
            admin.setUpdateTime(new Date());
            adminMapper.updateByPrimaryKeySelective(admin);
            adminCacheService.deleteResourceList(adminUid);
            OnlineAdmin onlineAdmin = adminCacheService.getOnlineAdmin(token);
            adminCacheService.deleteToken(onlineAdmin.getTokenUId());
            adminCacheService.deleteOnlineAdmin(token);
            return Wrapper.successWithMessage(AdminMessageConstant.UPDATE_SUCCESS);
        }
        return Wrapper.failed(AdminMessageConstant.UPDATE_FAIL);
    }

    @Override
    public List<OnlineAdmin> getOnlineAdminList(AdminDto adminDto) {
        List<OnlineAdmin> onlineAdminList = adminCacheService.getAllOnlineAdmin();
        Integer pageSize = adminDto.getPageSize();
        Integer currentPage = adminDto.getPageNum();
        Integer total = onlineAdminList.size();
        int startIndex = Math.max((currentPage - 1) * pageSize, 0);
        int size = Math.min(startIndex + pageSize, total);
        List<OnlineAdmin> pageList = onlineAdminList.subList(startIndex, size);
        for (OnlineAdmin onlineAdmin : pageList) {
            onlineAdmin.setToken("");
        }
        return onlineAdminList;
    }

    @Override
    public Wrapper forceLogout(List<String> tokenUidList) {
        for (String tokenUid : tokenUidList) {
            String token = adminCacheService.getToken(tokenUid);
            adminCacheService.deleteOnlineAdmin(token);
            adminCacheService.deleteToken(tokenUid);
        }
        return Wrapper.success();
    }

    /**
     * 根据用户名获取管理员信息
     * @param admin
     * @return
     */
    @Override
    public AdminDto getAdminByUsername(String username) {
        AdminExample example = new AdminExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andUsernameEqualTo(username);
        List<Admin> admins = adminMapper.selectByExample(example);
        Admin admin = admins.get(0);
        AdminDto adminDto = new AdminDto();
        MyBeanUtils.copyProperties(admin, adminDto);
        if (!StringUtils.isEmpty(admin.getHeadUid())) {
            Wrapper<String> pictureWrapper = pictureFeignApi.getPictureUrl(adminDto.getHeadUid());
            if (pictureWrapper.isSuccess()) {
                adminDto.setPhotoUrl(pictureWrapper.getData());
            }
        }
        return adminDto;
    }

    @Override
    public Admin getCurrentAdmin() {
        Integer adminUid = RequestHolder.getAdminUid();
        Admin admin = adminMapper.selectByPrimaryKey(adminUid);
        return admin;
    }
}
